import logging
import os
import sys
import time
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
import threading
from queue import Queue
import traceback
from typing import Dict, List, Optional, Union, Any, Protocol
from typing_extensions import runtime_checkable

# 定义日志级别常量，方便外部调用
DEBUG = logging.DEBUG
INFO = logging.INFO
WARNING = logging.WARNING
ERROR = logging.ERROR
CRITICAL = logging.CRITICAL

# 日志格式常量
DEFAULT_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
DETAILED_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s"
SIMPLE_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"

# 日志目录
DEFAULT_LOG_DIR = "logs"

@runtime_checkable
class LogFilter(Protocol):
    """日志过滤器协议，用于自定义日志过滤规则"""
    def filter(self, record: logging.LogRecord) -> bool:
        """过滤日志记录
        
        Args:
            record: 日志记录对象
            
        Returns:
            bool: True表示记录该日志，False表示过滤掉该日志
        """
        ...


class AsyncHandler(logging.Handler):
    """异步日志处理器，将日志写入操作放入队列，由后台线程处理"""
    
    def __init__(self, capacity: int = 1000):
        """初始化异步处理器
        
        Args:
            capacity: 队列容量，默认1000条日志
        """
        super().__init__()
        self.queue = Queue(capacity)
        self.handlers: List[logging.Handler] = []
        self._stop_event = threading.Event()
        self._thread = threading.Thread(target=self._process_logs, daemon=True)
        self._thread.start()
    
    def addHandler(self, handler: logging.Handler) -> None:
        """添加一个日志处理器
        
        Args:
            handler: 日志处理器
        """
        self.handlers.append(handler)
    
    def removeHandler(self, handler: logging.Handler) -> None:
        """移除一个日志处理器
        
        Args:
            handler: 日志处理器
        """
        if handler in self.handlers:
            self.handlers.remove(handler)
    
    def emit(self, record: logging.LogRecord) -> None:
        """发送日志记录到队列
        
        Args:
            record: 日志记录对象
        """
        try:
            self.queue.put(record, block=False)
        except Exception:
            self.handleError(record)
    
    def _process_logs(self) -> None:
        """后台线程处理日志队列"""
        while not self._stop_event.is_set() or not self.queue.empty():
            try:
                record = self.queue.get(block=True, timeout=0.2)
                for handler in self.handlers:
                    if record.levelno >= handler.level:
                        handler.emit(record)
                self.queue.task_done()
            except Exception:
                # 队列为空或其他错误，继续循环
                continue
    
    def close(self) -> None:
        """关闭异步处理器，等待队列处理完成"""
        self._stop_event.set()
        if self._thread.is_alive():
            self._thread.join(timeout=2.0)  # 等待最多2秒
        
        # 关闭所有处理器
        for handler in self.handlers:
            handler.close()
        
        super().close()


class Logger:
    """日志管理类，提供统一的日志接口"""
    
    _instances: Dict[str, 'Logger'] = {}
    _lock = threading.RLock()
    
    @classmethod
    def get_logger(cls, name: str = "app", **kwargs) -> 'Logger':
        """获取Logger实例，单例模式
        
        Args:
            name: 日志器名称
            **kwargs: 其他参数传递给__init__方法
            
        Returns:
            Logger: 日志器实例
        """
        with cls._lock:
            if name not in cls._instances:
                cls._instances[name] = cls(name, **kwargs)
            return cls._instances[name]
    
    def __init__(self, name: str = "app", level: int = INFO, 
                 log_dir: str = DEFAULT_LOG_DIR,
                 log_to_console: bool = True,
                 log_to_file: bool = True,
                 max_bytes: int = 10 * 1024 * 1024,  # 10MB
                 backup_count: int = 10,
                 format_str: str = DETAILED_FORMAT,
                 async_mode: bool = True,
                 daily_rotation: bool = False):
        """初始化日志器
        
        Args:
            name: 日志器名称
            level: 日志级别
            log_dir: 日志目录
            log_to_console: 是否输出到控制台
            log_to_file: 是否输出到文件
            max_bytes: 单个日志文件最大字节数
            backup_count: 备份文件数量
            format_str: 日志格式字符串
            async_mode: 是否使用异步模式
            daily_rotation: 是否按天切割日志
        """
        self.name = name
        self.level = level
        self.log_dir = log_dir
        self.format_str = format_str
        self.async_mode = async_mode
        
        # 创建日志目录
        if log_to_file and not os.path.exists(log_dir):
            os.makedirs(log_dir)
        
        # 创建日志器
        self.logger = logging.getLogger(name)
        self.logger.setLevel(level)
        self.logger.propagate = False
        
        # 清除已有的处理器
        for handler in self.logger.handlers[:]:  
            self.logger.removeHandler(handler)
        
        # 创建格式化器
        formatter = logging.Formatter(format_str)
        
        handlers = []
        
        # 添加控制台处理器
        if log_to_console:
            console_handler = logging.StreamHandler(sys.stdout)
            console_handler.setFormatter(formatter)
            console_handler.setLevel(level)
            handlers.append(console_handler)
        
        # 添加文件处理器
        if log_to_file:
            log_file = os.path.join(log_dir, f"{name}.log")
            
            if daily_rotation:
                # 按天切割日志
                file_handler = TimedRotatingFileHandler(
                    log_file, when='midnight', interval=1,
                    backupCount=backup_count, encoding='utf-8'
                )
            else:
                # 按大小切割日志
                file_handler = RotatingFileHandler(
                    log_file, maxBytes=max_bytes,
                    backupCount=backup_count, encoding='utf-8'
                )
            
            file_handler.setFormatter(formatter)
            file_handler.setLevel(level)
            handlers.append(file_handler)
        
        # 使用异步处理器
        if async_mode and handlers:
            async_handler = AsyncHandler()
            for handler in handlers:
                async_handler.addHandler(handler)
            self.logger.addHandler(async_handler)
            self.async_handler = async_handler
        else:
            # 直接添加处理器
            for handler in handlers:
                self.logger.addHandler(handler)
            self.async_handler = None
    
    def add_filter(self, log_filter: LogFilter) -> None:
        """添加日志过滤器
        
        Args:
            log_filter: 实现了filter方法的过滤器对象
        """
        self.logger.addFilter(log_filter)
    
    def debug(self, msg: Any, *args, **kwargs) -> None:
        """记录DEBUG级别日志
        
        Args:
            msg: 日志消息
            *args: 格式化参数
            **kwargs: 关键字参数
        """
        self.logger.debug(msg, *args, **kwargs)
    
    def info(self, msg: Any, *args, **kwargs) -> None:
        """记录INFO级别日志
        
        Args:
            msg: 日志消息
            *args: 格式化参数
            **kwargs: 关键字参数
        """
        self.logger.info(msg, *args, **kwargs)
    
    def warning(self, msg: Any, *args, **kwargs) -> None:
        """记录WARNING级别日志
        
        Args:
            msg: 日志消息
            *args: 格式化参数
            **kwargs: 关键字参数
        """
        self.logger.warning(msg, *args, **kwargs)
    
    def error(self, msg: Any, *args, exc_info: bool = False, **kwargs) -> None:
        """记录ERROR级别日志
        
        Args:
            msg: 日志消息
            *args: 格式化参数
            exc_info: 是否记录异常信息
            **kwargs: 关键字参数
        """
        self.logger.error(msg, *args, exc_info=exc_info, **kwargs)
    
    def critical(self, msg: Any, *args, exc_info: bool = True, **kwargs) -> None:
        """记录CRITICAL级别日志
        
        Args:
            msg: 日志消息
            *args: 格式化参数
            exc_info: 是否记录异常信息，默认为True
            **kwargs: 关键字参数
        """
        self.logger.critical(msg, *args, exc_info=exc_info, **kwargs)
    
    def exception(self, msg: Any, *args, **kwargs) -> None:
        """记录异常信息，级别为ERROR
        
        Args:
            msg: 日志消息
            *args: 格式化参数
            **kwargs: 关键字参数
        """
        self.logger.exception(msg, *args, **kwargs)
    
    def log(self, level: int, msg: Any, *args, **kwargs) -> None:
        """记录指定级别的日志
        
        Args:
            level: 日志级别
            msg: 日志消息
            *args: 格式化参数
            **kwargs: 关键字参数
        """
        self.logger.log(level, msg, *args, **kwargs)
    
    def set_level(self, level: int) -> None:
        """设置日志级别
        
        Args:
            level: 日志级别
        """
        self.level = level
        self.logger.setLevel(level)
        for handler in self.logger.handlers:
            handler.setLevel(level)
    
    def close(self) -> None:
        """关闭日志器，释放资源"""
        if self.async_handler:
            self.async_handler.close()
        
        # 从实例字典中移除
        with self.__class__._lock:
            if self.name in self.__class__._instances:
                del self.__class__._instances[self.name]


# 默认日志器
_default_logger: Optional[Logger] = None


def get_logger(name: str = "app", **kwargs) -> Logger:
    """获取指定名称的日志器
    
    Args:
        name: 日志器名称
        **kwargs: 传递给Logger初始化的参数
        
    Returns:
        Logger: 日志器实例
    """
    return Logger.get_logger(name, **kwargs)


def setup_default_logger(**kwargs) -> Logger:
    """设置默认日志器
    
    Args:
        **kwargs: 传递给Logger初始化的参数
        
    Returns:
        Logger: 默认日志器实例
    """
    global _default_logger
    _default_logger = get_logger("app", **kwargs)
    return _default_logger


def get_default_logger() -> Logger:
    """获取默认日志器，如果未设置则创建一个
    
    Returns:
        Logger: 默认日志器实例
    """
    global _default_logger
    if _default_logger is None:
        _default_logger = setup_default_logger()
    return _default_logger


# 便捷函数，使用默认日志器
def debug(msg: Any, *args, **kwargs) -> None:
    """使用默认日志器记录DEBUG级别日志"""
    get_default_logger().debug(msg, *args, **kwargs)


def info(msg: Any, *args, **kwargs) -> None:
    """使用默认日志器记录INFO级别日志"""
    get_default_logger().info(msg, *args, **kwargs)


def warning(msg: Any, *args, **kwargs) -> None:
    """使用默认日志器记录WARNING级别日志"""
    get_default_logger().warning(msg, *args, **kwargs)


def error(msg: Any, *args, exc_info: bool = False, **kwargs) -> None:
    """使用默认日志器记录ERROR级别日志"""
    get_default_logger().error(msg, *args, exc_info=exc_info, **kwargs)


def critical(msg: Any, *args, exc_info: bool = True, **kwargs) -> None:
    """使用默认日志器记录CRITICAL级别日志"""
    get_default_logger().critical(msg, *args, exc_info=exc_info, **kwargs)


def exception(msg: Any, *args, **kwargs) -> None:
    """使用默认日志器记录异常信息，级别为ERROR"""
    get_default_logger().exception(msg, *args, **kwargs)


def log(level: int, msg: Any, *args, **kwargs) -> None:
    """使用默认日志器记录指定级别的日志"""
    get_default_logger().log(level, msg, *args, **kwargs)